package editor{
	
	import components.ArrowLine;
	import components.FlowIcon;
	import components.RectBorder;
	
	import events.IconEvent;
	
	import flash.errors.IllegalOperationError;
	import flash.events.ContextMenuEvent;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.net.FileReference;
	import flash.ui.ContextMenu;
	import flash.ui.ContextMenuItem;
	
	import mx.collections.ArrayCollection;
	import mx.controls.Alert;
	import mx.controls.Image;
	import mx.controls.TextInput;
	import mx.core.Application;
	import mx.events.DataGridEvent;
	import mx.events.ItemClickEvent;
	
	import util.Utils;
	
	public class WFApplication extends Application{
	
		private var iconArray: Array = new Array(0);//存储所有的图片
		private var lineArray: Array = new Array(0);//存储所有的线条
		private var iconPressable: Boolean = false; //存储图标的按下状态
			
		//图标右键菜单
		[Bindable]
		private var cm: ContextMenu;
		
		//画布右键菜单
		[Bindable]
		private var canvasCm: ContextMenu;
		
		//属性对话框中的数据
		[Bindable]
		private var properties: ArrayCollection = new ArrayCollection();
			
		private var app: WorkflowexApp=new WorkflowexApp();
	
		public function WFApplication(){
	
		}
		
		internal function onContextMenu(event: Event): void{
				cm = new ContextMenu();
				cm.hideBuiltInItems();
				app.setFlow(flow);
				app.setIcons(icons_common,icons_task,icons_start,icons_end,icons_inter,icons_gateway);
			//	app.testXMLLoader();
				var mentItem1: ContextMenuItem = new ContextMenuItem("删除");
				cm.customItems.push(mentItem1);
				mentItem1.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, 
					function(e: ContextMenuEvent): void{
						var icon: FlowIcon = FlowIcon(e.contextMenuOwner);
						icon.selected = true;//先选中
						clearBorders();
						//删除所有选中的图标
						removeIconsFlow();
					});
			}
			
			
			
			
			//右击画布弹出的菜单
			internal function onCanvasContextMenu(event: Event): void{
				canvasCm = new ContextMenu();
				canvasCm.hideBuiltInItems();
				//全选菜单项
				var mi_selectAll: ContextMenuItem = new ContextMenuItem("全选", true);
				canvasCm.customItems.push(mi_selectAll);
				mi_selectAll.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,
					function(event: ContextMenuEvent): void{
						drawBorders();
					});
				//全不选菜单项
				var mi_selectNotAll: ContextMenuItem = new ContextMenuItem("全不选");
				canvasCm.customItems.push(mi_selectNotAll);
				mi_selectNotAll.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,
					function(event: ContextMenuEvent): void{
						clearBorders();
					});
				
				flow.contextMenu = canvasCm;
			}
			
			
			//鼠标点击流程图画布时,画出一个图标,如果指针不在任何图标上,则清除所有图标的蓝色边框
			internal function onFlowCanvasMouseDown(event: MouseEvent): void{
				//如果用户点击的是画布,而不是按钮冒泡过来的事件
				if(!(event.target is FlowIcon)){
					if(icons_common.selectedItem != null){
						if(icons_common.selectedIndex != 0 && icons_common.selectedIndex != 1){
							var newImage: FlowIcon = new FlowIcon(icons_common.selectedItem.icon,
								icons_common.selectedIndex);
								
							newImage.label = icons_common.selectedItem.label;
							//var newImage : Image = new Image();
							//newImage.source = icons.selectedItem.icon;
							//定位图标
							var p: Point = new Point();
							p = flow.globalToLocal(new Point(mouseX, mouseY));//转换坐标
							newImage.x = p.x;
							newImage.y = p.y;
							
							//newImage.addEventListener(MouseEvent.MOUSE_DOWN, onImageMouseDown);
							//newImage.addEventListener(MouseEvent.MOUSE_UP, onImageMouseUp);
							newImage.addEventListener(IconEvent.ICON_MOUSE_DOWN, onIconMouseDown);
							newImage.addEventListener(IconEvent.ICON_MOUSE_UP, onIconMouseUp);
							newImage.addEventListener(IconEvent.ICON_MOVE, onIconMove);
							//图片自动生成一个名字
							var n: String = Utils.randomString(10);
							newImage.name = "Name" + n;
							newImage.contextMenu = cm;
							
							//添加到图标集合中去
							iconArray.push(newImage);
							flow.addChild(newImage);
						}else{
							this.clearBorders();
							properties.removeAll();
						}
						icons_common.selectedIndex = 0; //重新选择第一个,不然老是添加了.
					}
				}
			}
			
			//当单击流程图画布上的图标时,呈选中状态,并出现发光效果.
			internal function onIconMouseDown(event: IconEvent): void{
				var img: FlowIcon = FlowIcon(event.icon);
				
				//建立连线
				var line: ArrowLine = this.drawLine(img);
				if(line != null){
					lineArray.push(line);
				}
				icons_common.selectedIndex = 0;
				
				//添加选中效果(发光)
				glow1.target = img;//将效果指定到图标上(编程时不是为图标设置效果)
				glow1.end();
				glow1.play();
				
				this.clearBorders(); //删除所有图标的边框
				
				//判断是否已经加了蓝色边框,如果加了就不需要再加了,只发光就行.
				//img.numChildren == 2的意思是:FlowIcon上已经有了图标和文字,没有边框
				if(img.numChildren == 2){
					//numChildren == 2表示还没有加蓝色边框
					this.drawBorder(img);
				}
				
				//设置属性对话框
				if(this.getSelectedIconCount() == 1)
					this.setProperties(img);
				else
					properties.removeAll();
				
				iconPressable = true;
				//实施拖动
				img.startDrag();
			}
			
			/**
			 * 拖动图标时重画与该图标相关的线条
			 */
			internal function onIconMove(event: IconEvent): void{
				if(iconPressable && event.target is FlowIcon){
					reDrawIcon(FlowIcon(event.target));
					
					this.setProperties(FlowIcon(event.icon));
				}
			}
			
			internal function onIconMouseUp(event: IconEvent): void{
				var img: Image = Image(event.icon);
				glow2.target = img;
				glow2.end();
				glow2.play();
				
				iconPressable = false;
				
				//停止拖动
				img.stopDrag();
			}
			
			internal function onTabIndexChanged(event: ItemClickEvent): void{
				if(event.index == 1){
					if(xmlHTML != null){
						xmlHTML.htmlText = this.xmlContent();
					}
				}
			}
			
			internal function onMenuClicked(event: ItemClickEvent): void{
				if(event.label=="打开"){
					openFile();
				}
				if(event.index == 1){
					if(xmlHTML != null){
						xmlHTML.htmlText = this.xmlContent();
					}
				}
			}
			
			internal function openFile():void{
				try{				
					
					var fileRef:FileReference=new FileReference();
					fileRef.browse();	
								
				}catch(illException:IllegalOperationError){
					trace("open file error");
				}
			}
			
			internal function onXmlHTMLComplete(event: Event): void{
				xmlHTML.htmlText = this.xmlContent();
			}
			
			/**
			 * 数据网格编辑完成
			 */
			internal function onGridEditEnd(event: DataGridEvent): void{
				var tf: TextInput = TextInput(dgProp.itemEditorInstance);
				var value: String = tf.text;
				//如果只有一个图标被选择
				var icon: FlowIcon = this.hasSelectedIcon();
				if(icon != null){
					switch(event.rowIndex){
						case 0:
							//从属性对话框中改变图标的name属性时，线条的fromIcon和toIcon都必须要改
							var length: int = lineArray.length;
							var line: ArrowLine = null;
							for(var i: int = 0; i < length; i ++){
								line = ArrowLine(lineArray[i]);
								if(line.fromIcon == icon.name){
									line.fromIcon = value;
								}
								if(line.toIcon == icon.name){
									line.toIcon = value;
								}
							}
							
							icon.name = value;
							break;
						case 1:
							icon.label = value;
							break;
						case 2:
							icon.memo = value;
							break;
						case 3:
							var n: Number = Number(value);
							if(n < 0) n = 0;
							icon.x = n;
							tf.text = n + "";
							break;
						case 4:
							n = Number(value);
							if(n < 0) n = 0;
							icon.y = n;
							tf.text = n + "";
							break;
						case 5:
							tf.text = icon.selected + "";
							break;
						case 6:
							tf.text = this.getType(icon.type);
							break;
					}
					
					reDrawIcon(icon);//重画
				}
				
			}
			
			/**
			 * 移动图标或从属性对话框里设置值时重新画一次
			 * 改变线程的XY坐标后会自动重画, 在ArrowLine.cs中已实现
			 */
			private function reDrawIcon(icon:  FlowIcon): void{
				if(icon.x <= 0) icon.x = 0;
					if(icon.y <= 0) icon.y = 0;
					
					//起始的
					var ac: ArrayCollection = this.getLines(icon.name, true);
					var length: int = ac.length;
					var line: ArrowLine = null;
					for(var i: int = 0; i < length; i ++){
						line = ArrowLine(ac.getItemAt(i));
						line.startX = icon.width / 2 + icon.x;
						line.startY = icon.height / 2 + icon.y;
					}
					
					//结束的
					ac = this.getLines(icon.name, false);
					length = ac.length;
					var p: Point = null;
					for(i = 0; i < length; i ++){
						line = ArrowLine(ac.getItemAt(i));
						p = this.getEndDotPosition(this.findIcon(line.fromIcon), icon);
						line.endX = p.x;
						line.endY = p.y;
					}
			}
			
			/**
			 * 为指定图标添加边框
			 */
			private function drawBorder(img: FlowIcon): void{
				var rect: RectBorder = new RectBorder(2, 0xFF0000, img.width, img.height, 0x000000, 2,2);
				img.selected = true; //保存选中状态
				img.addChild(rect);
			}
			
			/**
			 * 删除画布上所有的图标边框
			 */
			private function drawBorders():void{
				var length: int = flow.numChildren;
				var icon: Object = null;
				properties.removeAll();
				for(var i: int = 0; i < length; i ++){
					icon = flow.getChildAt(i);
					if(icon is FlowIcon){
						this.drawBorder(FlowIcon(icon));
					}
				}
			}
			
			//清除所有图标的边框
			private function clearBorders(): void{
				var currentImage: FlowIcon = null;
				for(var i: int = 0; i < flow.numChildren; i ++){
					if(flow.getChildAt(i) is mx.controls.Image){
						//找到当前的图标
						currentImage = FlowIcon(flow.getChildAt(i));
						//找到当前图标带蓝色方框的, 清除该方框
						if(this.hasBorderSprite(currentImage)){
							for(var j: int = currentImage.numChildren - 1; j >= 0; j --){
								if(this.hasBorderSprite(currentImage)){
									currentImage.selected = false;
									currentImage.removeChildAt(j);
								}
							}
						}
					}
				}
			}
			
			//检查Image内有没有BorderSprite,以便判断是否有蓝色边框
			private function hasBorderSprite(iconImage: Image): Boolean{
				for(var j: int = iconImage.numChildren - 1; j >= 0 ; j --){
					if(iconImage.getChildAt(j) is RectBorder){
						return true;
					}
				}
				return false;
			}
			
			/**
			 * 判断在画布内是否有选中的图标,如果有,则返回该图标,否则返回null
			 * 如果同时有多个图标被选择，则以第一个为准
			 */
			private function hasSelectedIcon(): FlowIcon{
				var icon: FlowIcon = null;
				for(var i: int = 0; i < iconArray.length; i ++){
					icon = FlowIcon(iconArray[i]);
					if(icon.selected){
						return icon;
					}
				}
				return null;
			}
			
			//画线
			private function drawLine(img: FlowIcon): ArrowLine{
				//先判断选择的是选择图标
				if(icons_common.selectedIndex == 1){
					//判断之前是否有选择的起始图标
					var beforeSelectedIcon: FlowIcon = this.hasSelectedIcon();
					
					if(beforeSelectedIcon != null && beforeSelectedIcon != img){
						if(hasLine(beforeSelectedIcon.name, img.name)){
							Alert.show("对不起,直线已存在", "错误");
							return null;
						}
						//在当前图标和之前选中的图标之间画线条
						//计算中心点
						var centerStartX: int = beforeSelectedIcon.width / 2;
						var centerStartY: int = beforeSelectedIcon.height / 2;
						
						var p: Point = this.getEndDotPosition(beforeSelectedIcon, img);
						
						var line: ArrowLine = new ArrowLine(
							centerStartX + beforeSelectedIcon.x,
							centerStartY + beforeSelectedIcon.y,
							p.x,
							p.y,
							0x000000,
							1,
							3,
							0x000000
						);
						
						//从..开始,到..结束
						line.fromIcon = beforeSelectedIcon.name;
						line.toIcon = img.name;
						line.name = "Line" + Utils.randomString(10);
						flow.addChild(line);
						return line;
					}
				}
				return null;
			}
			
			/**
			 * 画线时获取线条终点的坐标
			 * 判断终点图标和起始图标的相对位置,共九个
			 * 位置:左上,中上,右上;左中,中中,右中,左下,中下,右下
			 */
			private function getEndDotPosition(startIcon: FlowIcon, endIcon: FlowIcon): Point{
				var space: Number = 50;
				
				//计算起始点的中心点坐标
				var startCenterX: Number = startIcon.x + startIcon.width / 2;
				var startCenterY: Number = startIcon.y + startIcon.height / 2;
				
				//计算终点的中心点坐标
				var endCenterX: Number = endIcon.x + endIcon.width / 2;
				var endCenterY: Number = endIcon.y + endIcon.height / 2;
				
				var p: Point = new Point();
				
				//1左上
				if(endCenterX <= startCenterX - space && endCenterY <= startCenterY - space){
					p.x = endIcon.x + endIcon.width;
					p.y = endIcon.y + endIcon.height;
					//trace("左上");
				}
				//2中上
				else if(endCenterX >= startCenterX - space && endCenterX <= startCenterX + space
					&& endCenterY < startCenterY - space){
					p.x = endIcon.x + endIcon.width / 2;
					p.y = endIcon.y + endIcon.height;
					//trace("中上");
				}
				//3右上
				else if(endCenterX >= startCenterX + space && endCenterY <= startCenterY - space){
					p.x = endIcon.x;
					p.y = endIcon.y + endIcon.height;
					//trace("右上");
				}
				//4中左
				else if(endCenterX <= startCenterX - space && 
					endCenterY >= startCenterY - space && endCenterY <= startCenterY + space){
					p.x = endIcon.x + endIcon.width;
					p.y = endIcon.y + endIcon.height / 2;
					//trace("中左");
				}
				//5中中
				else if(endCenterX >= startCenterX - space && endCenterX <= startCenterX + space
					&& endCenterY >= startCenterY - space && endCenterY <= startCenterY + space){
					p.x = endIcon.x;
					p.y = endIcon.y;
					//trace("中中");
				}
				//6中右
				else if(endCenterX >= startCenterX + space && 
					endCenterY >= startCenterY - space && endCenterY <= startCenterY + space){
					p.x = endIcon.x;
					p.y = endIcon.y + endIcon.height / 2;
					//trace("中右");
				}
				//7下左
				else if(endCenterX <= startCenterX - space && endCenterY >= startCenterY + space){
					p.x = endIcon.x + endIcon.width;
					p.y = endIcon.y;
					//trace("下左");
				}
				//8下中
				else if((endCenterX >= startCenterX - space && endCenterX <= startCenterX + space) &&
					endCenterY >= startCenterY + space){
					p.x = endIcon.x + endIcon.width / 2;
					p.y = endIcon.y;
					//trace("下中");
				}
				//9右中
				else if(endCenterX >= startCenterX + space && endCenterY >= startCenterY + space){
					p.x = endIcon.x;
					p.y = endIcon.y;
					//trace("右中");
				}
				
				return p;
			}
			
			//判断两个图标之间是否已经有直线
			private function hasLine(fromIcon: String, toIcon: String): Boolean{
				var line: ArrowLine = null;
				var length: int = lineArray.length;
				for(var i:int = 0; i < length; i ++){
					line = ArrowLine(lineArray[i]);
					if(line.fromIcon == fromIcon && line.toIcon == toIcon){
						return true;
					}
				}
				return false;
			}
			
			/**
			 * 找到指定图标上所有的线条集合
			 */
			private function getLines(iconName: String, start: Boolean): ArrayCollection{
				var ac: ArrayCollection = new ArrayCollection();
				//遍历线条
				var length: int = lineArray.length;
				for(var i: int = 0; i < length; i ++){
					var obj: * = lineArray[i];
					if(start && obj.fromIcon == iconName){
						ac.addItem(obj);
					}else if((!start) && (obj.toIcon == iconName)){
						ac.addItem(obj);						
					}
				}
				return ac;
			}
			
			/**
			 * 删除与指定图标关联的所有线条
			 */
			private function removeLines(icon: FlowIcon): void{
				var length: int = lineArray.length;
				var line: ArrowLine = null;
				for(var i: int = length - 1; i >= 0 ; i --){
					line = lineArray[i];
					if(line.fromIcon == icon.name || line.toIcon == icon.name){
						flow.removeChild(line);
						lineArray.splice(i, 1); //同时删除数组中对应的元素
					}
				}
			}
			
			/**
			 * 删除多个图标
			 */
			private function removeIcons(icons: ArrayCollection): void{
				var icon: FlowIcon = null;
				var length: int = icons.length;
				for(var i: int = 0; i < length; i ++){
					icon = FlowIcon(icons.getItemAt(i));
					this.removeIcon(icon);
				}
			}
			
			/**
			 * 删除一个图标
			 */
			private function removeIcon(icon: FlowIcon): void{
				var length: int = iconArray.length;
				var curIcon: FlowIcon = null;
				//删除事件
				icon.removeEventListener(IconEvent.ICON_MOUSE_DOWN, onIconMouseDown);
				icon.removeEventListener(IconEvent.ICON_MOUSE_UP, onIconMouseUp);
				icon.removeEventListener(IconEvent.ICON_MOVE, onIconMove);
				flow.removeChild(icon); //删除图标
				//删除该图标上的所有直线
				this.removeLines(icon);
				
				//删除数组中的元素
				for(var i: int = length - 1; i >= 0; i --){
					curIcon = iconArray[i];
					if(curIcon.name == icon.name){
						iconArray.splice(i, 1);
					}
				}
				
				//清空属性对话框
				properties.removeAll();
			}
			
			/**
			 * 删除画布上的所有选中图标
			 */
			private function removeIconsFlow(): void{
				var length: int = flow.numChildren;
				var obj: Object = null;
				for(var i: int = length - 1; i >= 0; i --){
					obj = flow.getChildAt(i);
					if(obj is FlowIcon){
						if(obj.selected){
							this.removeIcon(FlowIcon(obj));
						}
					}
				}
			}
			
			/**
			 * 返回选中的图标个数
			 */
			private function getSelectedIconCount(): int{
				var length: int = iconArray.length;
				var total: int = 0;
				for(var i: int = 0; i < length; i ++){
					if(iconArray[i].selected){
						total ++;
					}
				}
				return total;
			}
			
			/**
			 * 找到指定图标的关联图标(只找与之关联的起点图标)
			 */
			private function getRelationIcons(icon: FlowIcon): ArrayCollection{
				var ac: ArrayCollection = new ArrayCollection();
				//先找到该图标上的所有线条（该图标为终点），再找与该线条相关的起点
				var length: int = lineArray.length;
				var line: ArrowLine = null;
				for(var i: int = 0; i < length; i ++){
					line = ArrowLine(lineArray[i]);		
					if(line.toIcon == icon.name){
						ac.addItem(this.findIcon(line.fromIcon));
					}
				}
				return ac;
			}
			
			/**
			 * 根据图标的名称找到该图标
			 */
			private function findIcon(name: String): FlowIcon{
				var length: int = iconArray.length;
				for(var i: int = 0; i < length; i ++){
					if(iconArray[i].name == name){
						return iconArray[i];
					}
				}
				return null;
			}
			
			private function xmlContent():String{
				var x: String = "&lt;workflow&gt;<br>";
				var node: String = "";
				var length: int = iconArray.length;
				for(var i: int = 0; i < length; i ++){
					node = Utils.space(4) + "&lt;" + Utils.nodeHTML("node") + 
						" " + Utils.attributeHTML("name") + "=\"" + iconArray[i].name + 
						"\" " + Utils.attributeHTML("label") + "=\"" +  iconArray[i].label +
						"\" " + Utils.attributeHTML("type") + "=\"" + iconArray[i].type +
						"\" " + Utils.attributeHTML("selected") + "=\"" + iconArray[i].selected +
						"\" " + Utils.attributeHTML("memo") + "=\"" + iconArray[i].memo +
						"\" " + Utils.attributeHTML("x") + "=\"" + iconArray[i].x +
						"\" " + Utils.attributeHTML("y") + "=\"" + iconArray[i].y +
						"/&gt;";
						
					x += node + "<br>";
				}
				
				length = lineArray.length;
				for(i = 0; i < length; i ++){
					node = Utils.space(4) + "&lt;" + Utils.nodeHTML("line") + 
						" " + Utils.attributeHTML("name") + "=\"" +  lineArray[i].name +
						"\" " + Utils.attributeHTML("startX") + "=\"" + lineArray[i].startX + 
						"\" " + Utils.attributeHTML("startY") + "=\"" +  lineArray[i].startY +
						"\" " + Utils.attributeHTML("endX") + "=\"" + lineArray[i].endX +
						"\" " + Utils.attributeHTML("endY") + "=\"" + lineArray[i].endY +
						"\" " + Utils.attributeHTML("fromIcon") + "=\"" + lineArray[i].fromIcon +
						"\" " + Utils.attributeHTML("toIcon") + "=\"" + lineArray[i].toIcon +
						"/&gt;";
						
					x += node + "<br>";
				}
				x += "&lt;/workflow&gt;";
				return x;
			}
			
			private function setProperties(icon:FlowIcon): void{
				properties.removeAll();
				
				properties.addItem({name: "名称", value: icon.name});	
				properties.addItem({name: "标签", value: icon.label});
				properties.addItem({name: "备注", value: icon.memo});
				properties.addItem({name: "X坐标", value: icon.x});	
				properties.addItem({name: "Y坐标", value: icon.y});	
				properties.addItem({name: "选择", value: icon.selected});
				properties.addItem({name: "类型", value: getType(icon.type)});			
			}
			
			private function getType(index: int): String{
				return index == 2 ? "流程" : 
					index == 3 ? "计算" : 
					index == 4 ? "页面" : 
					index == 5 ? "调用" : 
					index == 6 ? "分支" : 
					index == 7 ? "会合" : 
					index == 8 ? "开始" : "结束";
			}
			
			//test
			private function printIconsStatus(): void{
				for(var i: int = 0; i < iconArray.length; i ++){
					if(iconArray[i] is FlowIcon){
						trace(FlowIcon(iconArray[i]).selected);
					}
				}
			}

	}
}